package com.onpositive.dataminer.value.audits;

import java.util.HashMap;
import java.util.Map;

import com.onpositive.data.IPropertyConstants;
import com.onpositive.dataminer.core.DefaultUniverse;
import com.onpositive.knowledge.model.value.audits.AbstractAuditResult;
import com.onpositive.knowledge.model.value.audits.AbstractUniverseAudit;
import com.onpositive.knowledge.model.value.audits.IUniverseAudit;
import com.onpositive.knowledge.model.values.DescribedValue;
import com.onpositive.semantic.model.api.meta.IMeta;
import com.onpositive.semantic.model.api.property.IProperty;
import com.onpositive.units.ParsedIdent;
import com.onpositive.wiki3.db.IRedirectAccess;
import com.onpositive.wiki3.db.IWikiDB;

public class WikiLinksRedirectionAudit extends AbstractUniverseAudit {

	private static final long serialVersionUID = -9109542069183836768L;
	
	public final static String ID = "reference-redirection-audit" ;
	
	public WikiLinksRedirectionAudit() {
		super();
	}
	
	private IWikiDB wikiDB;
	
	private IRedirectAccess redirectAccess;

	@Override
	public void perform( Iterable<IProperty> properties, Iterable<Object> objects, AbstractAuditResult auditResult) {
		
		if(!(auditResult instanceof OwnAuditResult))
			return;
		
		initRedirectAccess();
		if(redirectAccess==null)
			return;
		
		Map<String,Object> metaInfo = new HashMap<String, Object>() ;
		metaInfo.put("audit-result", auditResult) ;		
		iterateProperties(properties, objects, metaInfo, 0);	
		auditResult.setLooksApplyable(true) ;
		
		disposeRedirectAccess();
	}


	private void disposeRedirectAccess() {
		
		wikiDB=null;
		redirectAccess=null;		
	}


	private void initRedirectAccess() {		
		if(wikiDB==null){
			IMeta meta = DefaultUniverse.getInstance().getMeta();
			if(meta!=null){
				IWikiDB service = meta.getService(IWikiDB.class);
				if(service != null)
					wikiDB = service;
			}
			
		}
		
		if(redirectAccess==null&&wikiDB!=null)
			redirectAccess = wikiDB.getRedirectAccess();		
	}


	@Override
	public void iterateProperties(Iterable<IProperty> properties, Iterable<Object> objects, Map<String,Object> metaInfo, int ind)
	{
		for( IProperty prop : properties ){
			
			@SuppressWarnings("unused")
			String name = prop.getMeta().getSingleValue( "id", String.class, null ) ;			
			
			Boolean isService = prop.getMeta().getSingleValue( IPropertyConstants.CHAR_IS_SERVICE_PROPERTY, Boolean.class, null) ;
			if( isService != null && isService )
				continue ;
			
			Boolean isDepricated = prop.getMeta().getSingleValue( IPropertyConstants.CHAR_DEPRICATED_LABEL, Boolean.class, null);
			if( isDepricated != null && isDepricated )
				continue ;			
			
			iterateObjects( prop, objects, metaInfo, ind );
		}
	}
	
	@Override
	protected void process(IProperty prop, Object val, Map<String,Object> metaInfo, int index) {
		
		if( !(val instanceof ParsedIdent) )
			return ;	
		
		Object resultObject = metaInfo.get("audit-result");
		if( resultObject == null || !(resultObject instanceof OwnAuditResult) )
			return ;
		
		ParsedIdent ident = (ParsedIdent) val ;		
		OwnAuditResult result = (OwnAuditResult) resultObject;
		
		String ref = ident.getRef();
		if(ref==null)
			return;
		
		String redirect = redirectAccess.normalizeTitle(ref);
		if(redirect==null||redirect.equals(ref))
			return;
		
		result.addRedirect(ref, redirect);		
	}

	
	public AbstractAuditResult createAuditResult() {
		return new OwnAuditResult( this );
	}


	protected Class<?>[] createNecessaryClasses() {
		return new Class<?>[]{ ParsedIdent.class };
	}

	protected Class<?>[] createTargetClasses() {
		return new Class<?>[]{ ParsedIdent.class };
	}

	protected boolean isSuspicious(Object o, DescribedValue value,
			IProperty prop,AbstractAuditResult pm)
	{
		return false ;
	}
	
	public static class OwnAuditResult extends AbstractAuditResult{

		private static final long serialVersionUID = -7196555376554623882L;

		public OwnAuditResult(IUniverseAudit audit) {
			super(audit);
		}
		
		private HashMap<String,String> map = new HashMap<String, String>();
		
		public void addRedirect(String ref,String redirect){
			map.put(ref, redirect);
		}
		
		public String getRedirect(String ref){
			return map.get(ref);
		}				
	}

	@Override
	public String getId() {
		return ID;
	}
}
